﻿//-----------------------------------------------------------------------
// <copyright file="IMembershipRepository.cs" company="OOHM PROCESSAMENTO DE DADOS LTDA.">
//     Microsoft Public License (MS-PL) This license governs use of the accompanying
//     software. If you use the software, you accept this license. If you do not
//     accept the license, do not use the software. 1. Definitions The terms "reproduce,"
//     "reproduction," "derivative works," and "distribution" have the same meaning
//     here as under U.S. copyright law. A "contribution" is the original software,
//     or any additions or changes to the software. A "contributor" is any person
//     that distributes its contribution under this license. "Licensed patents"
//     are a contributor's patent claims that read directly on its contribution.
//     2. Grant of Rights (A) Copyright Grant- Subject to the terms of this license,
//     including the license conditions and limitations in section 3, each contributor
//     grants you a non-exclusive, worldwide, royalty-free copyright license to
//     reproduce its contribution, prepare derivative works of its contribution,
//     and distribute its contribution or any derivative works that you create.
//     (B) Patent Grant- Subject to the terms of this license, including the license
//     conditions and limitations in section 3, each contributor grants you a non-exclusive,
//     worldwide, royalty-free license under its licensed patents to make, have
//     made, use, sell, offer for sale, import, and/or otherwise dispose of its
//     contribution in the software or derivative works of the contribution in
//     the software. 3. Conditions and Limitations (A) No Trademark License- This
//     license does not grant you rights to use any contributors' name, logo, or
//     trademarks. (B) If you bring a patent claim against any contributor over
//     patents that you claim are infringed by the software, your patent license
//     from such contributor to the software ends automatically. (C) If you distribute
//     any portion of the software, you must retain all copyright, patent, trademark,
//     and attribution notices that are present in the software. (D) If you distribute
//     any portion of the software in source code form, you may do so only under
//     this license by including a complete copy of this license with your distribution.
//     If you distribute any portion of the software in compiled or object code
//     form, you may only do so under a license that complies with this license.
//     (E) The software is licensed "as-is." You bear the risk of using it. The
//     contributors give no express warranties, guarantees or conditions. You may
//     have additional consumer rights under your local laws which this license
//     cannot change. To the extent permitted under your local laws, the contributors
//     exclude the implied warranties of merchantability, fitness for a particular
// </copyright>
//-----------------------------------------------------------------------
namespace AbstractSaaSTemplate.Domain.Repositories{    using System;
    using System.Collections.Generic;
    using AbstractSaaSTemplate.Domain.Models.Entities;
    using AbstractSaaSTemplate.Domain.Models.Enumerators;

    /// <summary>
    /// Describes the contract for the 'Membership' repository.
    /// </summary>
    public interface IMembershipRepository : IRepository
    {
        /// <summary>
        /// Retrieves an account by its id.
        /// </summary>
        /// <param name="id">The id of the account.</param>
        /// <returns>If found, returns an instance of Account; otherwise returns null.</returns>
        Account GetAccountById(long id);
        
        /// <summary>
        /// Creates or updates a 'User' in the system.
        /// </summary>
        /// <param name="entity">The entry of 'User' which will be either created or updated.</param>
        void AddOrUpdateUser(User entity);

        /// <summary>
        /// Gets a 'User' by its id.
        /// </summary>
        /// <param name="id">The id of the User.</param>
        /// <returns>Returns an instance of User.</returns>
        User GetUserById(long id);

        /// <summary>
        /// Gets a 'User' by its login.
        /// </summary>
        /// <param name="login">The login which will be matched to find the 'User'.</param>
        /// <returns>If found, returns the instance of 'User'; otherwise, returns null.</returns>
        User GetUserByCredentials(string login);

        /// <summary>
        /// Gets a 'User' by its login and password.
        /// </summary>
        /// <param name="login">The login which will be matched to find the user.</param>
        /// <param name="password">The password which will be mached to find the user.</param>
        /// <returns>If found, returns the instance of 'User'; otherwise, returns null.</returns>
        User GetUserByCredentials(string login, string password);

        /// <summary>
        /// Gets a 'User' by its email address.
        /// </summary>
        /// <param name="emailAddress">The emailAddress which will be matched to find the user.</param>
        /// <returns>If found, returns the instance of 'User'; otherwise, returns null.</returns>
        User GetUserByEmailAddress(string emailAddress);

        /// <summary>
        /// Retrieves a list of 'User' who match to the role
        /// </summary>
        /// <param name="level">The accesslevel for which we will try to find a matching user.</param>
        /// <param name="role">The role for which we will try to find a matching user.</param>
        /// <returns>Returns a list of User</returns>
        IEnumerable<User> GetUsersByRole(AccessLevels level, AccessRoles role);
        
        /// <summary>
        /// Retrieves a list of 'User' who match to the role
        /// </summary>
        /// <param name="role">Returns a list of User.</param>
        /// <returns>Returns a list of User</returns>
        IEnumerable<User> GetUsersByRole(AccessRoles role);

        /// <summary>
        /// Retrieves a list of 'User' who are related to a tenant.
        /// </summary>
        /// <param name="tenantId">The id of the tenant.</param>
        /// <returns>Returns a list of User</returns>
        IEnumerable<User> GetUsersByTenantId(long tenantId);

        /// <summary>
        /// Retrieves a list of 'User' who are related to a tenant.
        /// </summary>
        /// <param name="tenantId">The id of the tenant.</param>
        /// <param name="role">The role for which we will retrieve the users</param>
        /// <returns>Returns a list of User</returns>
        IEnumerable<User> GetUsersByTenantIdAndRole(long tenantId, AccessRoles role);
        
        /// <summary>
        /// Gets the list of roles related to a particular user.
        /// </summary>
        /// <param name="login">The login of the user for which the roles will be loaded.</param>
        /// <returns>Returns a list of Role</returns>
        IEnumerable<AccessRoles> GetRolesByCredentials(string login);

        /// <summary>
        /// Gets a list of all features related to the role for a specific access level.
        /// </summary>
        /// <param name="level">The access level.</param>
        /// <returns>Returns a list of associations between role, access levels and features.</returns>
        IEnumerable<RoleFeature> GetRoleFeaturesByAccessLevel(AccessLevels level);

        /// <summary>
        /// Generates an association between the user
        /// and the key of the role.
        /// </summary>
        /// <param name="userId">The id of the user.</param>
        /// <param name="role">The key of the role.</param>
        /// <returns>Returns a instance of 'UserRole' which is the association.</returns>
        UserRole AssociateUserWithRole(long userId, AccessRoles role);

        /// <summary>
        /// Generates an association between the user and the tenant.
        /// </summary>
        /// <param name="userId">The id of the user.</param>
        /// <param name="tenantId">The id of the tenant.</param>
        /// <returns>Returns a instance of 'UserTenant' which is the association.</returns>
        UserTenant AssociateUserWithTenant(long userId, long tenantId);

        /// <summary>
        /// Generates an association between the role and the controlled feature.
        /// </summary>
        /// <param name="level">The access level of the role and feature.</param>
        /// <param name="role">The role which will be checked.</param>
        /// <param name="feature">The feature which is being accessed.</param>
        /// <returns>Returns a instance of 'RoleFeature' which is the association.</returns>
        RoleFeature AssociateRoleWithFeature(
            AccessLevels level,
            AccessRoles role,
            ControlledFeatures feature);

        /// <summary>
        /// Removes an association related to level, role and feature.
        /// </summary>
        /// <param name="level">The access level of the role and feature.</param>
        /// <param name="role">The role which will be checked.</param>
        /// <param name="feature">The feature which is being accessed.</param>
        void RemoveAssociationBetweenRoleAndFeature(
            AccessLevels level,
            AccessRoles role,
            ControlledFeatures feature);

        /// <summary>
        /// Retrieves a User x Role association if existing.
        /// </summary>
        /// <param name="user">The user for which we are attempting to retrieve the association.</param>
        /// <param name="role">The role for which we are attempting to retrieve the association.</param>
        /// <returns>If exists, returns a UserRole association; otherwise returns false.</returns>
        UserRole GetUserRoleAssociation(User user, AccessRoles role);

        /// <summary>
        /// Retrieves a AccessLevel and Role x Feature association if existing.
        /// </summary>
        /// <param name="level">The access level of the role and feature.</param>
        /// <param name="role">The role which will be checked.</param>
        /// <param name="feature">The feature which is being accessed.</param>
        /// <returns>If exists, returns a RoleFeature association; otherwise returns false.</returns>
        RoleFeature GetRoleFeatureAssociation(AccessLevels level, AccessRoles role, ControlledFeatures feature);

        /// <summary>
        /// Retrives the list of User related to a particular access level.
        /// </summary>
        /// <param name="level">The access level for which the Users will be retrieved.</param>
        /// <returns>Returns an enumerable of User related to a particular access level.</returns>
        IEnumerable<User> GetUsers(AccessLevels level);

        /// <summary>
        /// Retrives the list of User related to a particular access level.
        /// </summary>
        /// <param name="visibleToUserId">The id of the user, so that we can check for related tenants or accounts, depending on the level.</param>
        /// <param name="level">The access level for which the Users will be retrieved.</param>
        /// <returns>Returns an enumerable of User related to a particular access level.</returns>
        IEnumerable<User> GetUsers(long visibleToUserId, AccessLevels level);
    }
}


